MindReading

Neurosynth-pt2

Letzte Woche haben wir gesagt, dass Vorhersagen der Gehirnaktivität einer Person aus der Aktivität anderer Personen nicht nur schwieriger ist, sondern auch Potential hat.

Was Besonderheiten der Aufgaben angeht, so haben wir zwar bei Neurosynth den Nachteil, dass es (zumindest ohne viel manueller Arbeit), nicht möglich ist nur nach Gesichterstudien zu suchen, bei denen die Gesichter bloß vorgestellt werden sollten. Daher werden unsere Aktivierungen zu denen aus anderen Gesichterstudien nicht allzu gut passen.

Aber wir haben den großen Vorteil, dass wir zur Zeit ca. 3000 verschiedene Stichwörter in Neurosynth haben, von denen viele Synonyme sind (face,faces,facial etc.) oder bedeutungslos (magnetic, gyrus), aber die meisten sind für uns schon ganz interessant. Was für Möglichkeiten eröffnet das? Während wir mit unserer Versuchsperson kaum mehr als ein paar Bedingungen in einer Stunde durchlaufen können, haben wir hier eine Datenbank mit mindestens mehreren hundert Karten für spezifische Prozesse. Das heißt, dass wir versuchen können, Hirnbilder unserer Person zu dekodieren, wo sie an Dinge gedacht hat die nie in unserem Trainingsdatensatz waren. Das heißt, dass wir jemanden in den Scanner legen könnten und sofort jeden nur vorstellbaren Gedanken noch so fein aufschlüsseln könnten, egal ob wir Trainingsdaten haben und egal an was die Person denkt. Das hat aber seine Grenzen, weil sehr spezifische Gedanken nicht unbedingt auf die gleiche Art in unser aller Gehirn repräsentiert sind. Vielleicht verarbeiten wir alle Gesichter in der FFA, aber wir haben nicht alle das gleiche Aktivierungsmuster in der FFA wenn wir ein fröhliches Gesicht sehen etc.

Wir vergleichen heute ein paar hundert Karten aus Neurosynth erst untereinander (um Gruppen von ähnlichen Funktionen zu finden) und dann mit jedem Block unserer Versuchsperson. Das ergibt viele Daten, die wir entsprechend in einer vereinfachten Art und Weise darstellen wollen.

Wir machen uns eine Liste mit allen unseren Hirnbildern

In [1]:
import os
In [2]:
imgList = ['../training/%s'%x for x in os.listdir('../training/') if x.startswith('s00')]; imgList.sort()

Whole-Brain Maske

Hier benutzen wir eine grobe Maske mit 4mm Auflösung, weil die Berechnungen sonst zu lange dauern

In [3]:
from nilearn import image, plotting, input_data 
In [4]:
import pickle
In [5]:
my_masker = input_data.NiftiMasker(mask_img='../masks/gmMap4mm.nii.gz').fit()
In [6]:
my_masker
Out[6]:
NiftiMasker(detrend=False, high_pass=None, low_pass=None, mask_args=None,
      mask_img='../masks/gmMap4mm.nii.gz', mask_strategy='background',
      memory=Memory(cachedir=None), memory_level=1, sample_mask=None,
      sessions=None, smoothing_fwhm=None, standardize=False, t_r=None,
      target_affine=None, target_shape=None, verbose=0)
In [7]:
plotting.plot_roi(my_masker.mask_img_);

Daten extrahieren

In [8]:
from sklearn import preprocessing
In [9]:
def extractMaps(fileName,my_masker):
    thisData = my_masker.transform(fileName)[-1]
    scaleData = preprocessing.scale(thisData)
    return scaleData

Um das Ganze erstmal beispielhaft durchzugehen, nehmen wir uns einen einzelnen Block aus unseren Daten

In [10]:
thisMap = imgList[-19]
In [11]:
scaleMap = extractMaps(thisMap,my_masker)
/data/martin/seminarSS18/venv/lib/python2.7/site-packages/scipy/ndimage/interpolation.py:435: UserWarning: The behaviour of affine_transform with a one-dimensional array supplied for the matrix parameter will change in scipy 0.18.0.
  "The behaviour of affine_transform with a one-dimensional "
In [12]:
scaleMap
Out[12]:
array([-0.54883461, -1.34914072, -1.34716611, ...,  1.61947098,
        0.51583733,  0.14877121])

wir laden ca. 600 Karten aus Neurosynth, die ich vorher ausgewählt habe

Die Einschlusskriterien waren, dass die Maske nicht leer sein darf (Stichwörter wie "magnetic" sind so unspefifisch, dass sie keine Voxel enthalten; außerdem gibt es sehr viele Karten, die zwar Voxel enthalten, aber keinem inhaltlich interpertierbaren psychologischen Prozess zugeordnet werden können (z.B. white matter, young, old, patient, healthy).

In [13]:
import pandas as pd
In [14]:
nsData = pd.read_csv('../arrays/ns_4mm_database.csv',index_col=[0,1])
In [15]:
nsData
Out[15]:
0 1 2 3 4 5 6 7 8 9 ... 18734 18735 18736 18737 18738 18739 18740 18741 18742 18743
Unnamed: 1
0 angular -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 ... -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818 -0.112818
angular gyrus -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 ... -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733 -0.118733
anterior medial -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 ... -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995 -0.096995
autobiographical -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 ... 3.583134 -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 -0.308027 3.466874 -0.308027
autobiographical memory -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 ... -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477 -0.255477
belief -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 ... -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477 -0.121477
beliefs -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 ... -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680 -0.179680
cognitive task -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 ... -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713 -0.084713
coherent -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 ... -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727 -0.094727
component -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 ... -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105 -0.030105
component ica -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 7.637382 ... -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041 -0.146041
connectivity -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 ... -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641 -0.108641
connectivity networks -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 7.592583 ... -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103 -0.148103
construction -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 ... -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752 -0.142752
cortex mpfc -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 ... -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563 -0.165563
cortex pcc -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 ... -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599 -0.110599
cortex posterior -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 ... -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295 -0.120295
cortex precuneus -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 ... -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598 -0.160598
cortex vmpfc -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 ... -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151 -0.135151
deactivation -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 ... -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391 -0.154391
default -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 ... -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 -0.268923 4.120744 -0.268923 -0.268923
default mode -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 ... -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627 -0.227627
default network -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 ... 4.957990 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868 -0.217868
dmn -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 ... -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 -0.167034 6.637182 -0.167034 -0.167034
dorsal attention -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 ... -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275 -0.100275
dorsomedial -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 ... -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129 -0.108129
dorsomedial prefrontal -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 ... -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136 -0.142136
episodic -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 3.695869 ... -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263 -0.301263
episodic memory -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 ... -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077 -0.250077
functional connectivity -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 ... 7.967443 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237 -0.138237
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
7 opercularis -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 ... -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529
orthographic -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 ... -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586 -0.198586
pairs -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 ... -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705 -0.069705
pars -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 ... -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385 -0.067385
pars opercularis -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 ... -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529 -0.070529
phonological -0.287132 -0.287132 -0.287132 -0.287132 -0.287132 -0.287132 -0.287132 -0.287132 -0.287132 -0.287132 ... -0.287132 -0.287132 -0.287132 -0.287132 -0.287132 3.746134 -0.287132 -0.287132 -0.287132 -0.287132
posterior inferior -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 ... -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829 -0.093829
posterior middle -0.129101 -0.129101 -0.129101 -0.129101 -0.129101 8.167471 8.297923 8.608755 -0.129101 -0.129101 ... -0.129101 -0.129101 -0.129101 -0.129101 -0.129101 -0.129101 -0.129101 -0.129101 -0.129101 8.426726
posterior temporal 7.723568 -0.142686 -0.142686 -0.142686 7.557156 7.576015 7.408480 -0.142686 -0.142686 -0.142686 ... -0.142686 -0.142686 -0.142686 7.448925 7.249491 7.049437 -0.142686 -0.142686 -0.142686 -0.142686
pseudowords -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 ... -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868 -0.128868
read -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 ... -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065 -0.112065
readers -0.135372 -0.135372 -0.135372 -0.135372 -0.135372 7.908803 -0.135372 -0.135372 -0.135372 -0.135372 ... -0.135372 -0.135372 -0.135372 -0.135372 -0.135372 -0.135372 -0.135372 -0.135372 -0.135372 -0.135372
reading -0.256289 -0.256289 -0.256289 -0.256289 -0.256289 4.105769 -0.256289 -0.256289 -0.256289 -0.256289 ... -0.256289 -0.256289 -0.256289 -0.256289 -0.256289 -0.256289 -0.256289 -0.256289 -0.256289 -0.256289
representations -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 ... -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898 -0.047898
semantic -0.294634 -0.294634 -0.294634 3.630281 3.690962 3.619796 3.625032 3.569274 -0.294634 -0.294634 ... -0.294634 -0.294634 -0.294634 -0.294634 -0.294634 -0.294634 -0.294634 -0.294634 -0.294634 -0.294634
semantic information -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 ... -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968 -0.071968
semantically -0.092958 -0.092958 -0.092958 -0.092958 -0.092958 -0.092958 11.569550 -0.092958 -0.092958 -0.092958 ... -0.092958 -0.092958 -0.092958 -0.092958 -0.092958 -0.092958 -0.092958 -0.092958 -0.092958 11.969973
semantics -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 ... -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119 -0.079119
sentence -0.222525 -0.222525 -0.222525 4.772203 5.108854 5.074188 4.783304 -0.222525 -0.222525 -0.222525 ... -0.222525 -0.222525 -0.222525 -0.222525 -0.222525 -0.222525 -0.222525 -0.222525 -0.222525 -0.222525
sentence comprehension -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 ... -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672 -0.090672
sentences -0.249918 -0.249918 -0.249918 4.490037 4.466338 4.431488 4.213420 -0.249918 -0.249918 -0.249918 ... -0.249918 -0.249918 -0.249918 -0.249918 -0.249918 -0.249918 -0.249918 -0.249918 -0.249918 -0.249918
speakers -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 ... -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308 -0.071308
syntactic -0.149024 -0.149024 -0.149024 -0.149024 -0.149024 7.127379 6.890383 7.298332 -0.149024 -0.149024 ... -0.149024 -0.149024 -0.149024 -0.149024 -0.149024 -0.149024 -0.149024 -0.149024 -0.149024 -0.149024
temporal cortex -0.152570 -0.152570 -0.152570 -0.152570 -0.152570 -0.152570 -0.152570 -0.152570 -0.152570 -0.152570 ... -0.152570 -0.152570 -0.152570 -0.152570 6.984804 -0.152570 -0.152570 -0.152570 -0.152570 -0.152570
verb -0.140734 -0.140734 -0.140734 7.730728 7.511163 7.774626 7.369451 7.784234 -0.140734 -0.140734 ... -0.140734 -0.140734 -0.140734 -0.140734 -0.140734 -0.140734 -0.140734 -0.140734 -0.140734 -0.140734
verbal -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 ... -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669 -0.096669
verbs -0.143120 -0.143120 -0.143120 -0.143120 7.498145 7.815414 7.668591 7.714716 7.300322 -0.143120 ... -0.143120 -0.143120 -0.143120 -0.143120 -0.143120 -0.143120 -0.143120 -0.143120 -0.143120 -0.143120
word -0.238959 -0.238959 -0.238959 -0.238959 4.465387 4.689173 4.569203 4.486181 -0.238959 -0.238959 ... -0.238959 -0.238959 -0.238959 -0.238959 -0.238959 -0.238959 -0.238959 -0.238959 -0.238959 -0.238959
words -0.268781 -0.268781 -0.268781 -0.268781 3.830119 4.113190 4.155813 4.230690 -0.268781 -0.268781 ... -0.268781 -0.268781 -0.268781 -0.268781 -0.268781 -0.268781 -0.268781 -0.268781 -0.268781 -0.268781
written -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 ... -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325 -0.133325

602 rows × 18744 columns

Die Daten wurden mittels Clusteranalyse in 8 verschiedene Cluster eingeteilt, denen wir erstmal keine Namen geben; das können Sie selbst einmal machen, indem Sie sich erstmal die Ergebnisse unten ansehen, dann die Werte hier ändern und dann alles ab hier noch mal ausführen.

In [16]:
clusterNames = {'0':'a',
                '1':'b',
                '2':'c',
                '3':'d',
                '4':'e',
                '5':'f',
                '6':'g',
                '7':'h',
               }

Korrelation eines Blocks unserer Daten mit allen 602 Karten

In [17]:
import numpy as np
In [18]:
thisCorr = np.corrcoef(scaleMap,nsData)[0,:][1:]
In [19]:
thisCorrDf = pd.DataFrame(thisCorr,index=nsData.index,columns=['corr']).T
In [20]:
thisCorrDf
Out[20]:
0 ... 7
Unnamed: 1 angular angular gyrus anterior medial autobiographical autobiographical memory belief beliefs cognitive task coherent component ... sentences speakers syntactic temporal cortex verb verbal verbs word words written
corr -0.041474 -0.04091 -0.00513 -0.029993 -0.025134 -0.043497 -0.044488 -0.009527 -0.021376 -0.015358 ... -0.023007 0.006428 -0.002972 -0.015215 0.001032 0.019937 0.004898 0.015984 -0.000451 0.001577

1 rows × 602 columns

Wir sortieren nach Stärke der Korrelation

Sonst müssten wir die 602 Korrelationen einzeln durchgehen um bedeutsame Zusammenhänge zu finden.

In [21]:
def getTop(corrDf):
    sortDf = corrDf.copy()
    sortDf = sortDf.T.sort_values(by=sortDf.index[-1],ascending=False)
    topDf = pd.concat([sortDf[:5],sortDf[-5:]],axis=0)
    topDf.columns = ['correlation']
    topDf = topDf.round(2)
    return topDf
In [22]:
topDf = getTop(thisCorrDf)

Beispiel: Die fünf höchstn und die fünf niedrigsten Korrelationen des gewählten Blocks

In [23]:
topDf
Out[23]:
correlation
Unnamed: 1
1 premotor 0.14
movements 0.13
5 superior parietal 0.13
1 motor 0.12
finger movements 0.12
0 temporo parietal -0.06
default mode -0.06
mental states -0.06
theory mind -0.07
precuneus -0.07

Auflösung: was war unser Block?

In [24]:
thisMap
Out[24]:
'../training/s00MOTORIK_028_Fuesse-Hochseil.nii.gz'

Die 602 Karten in Neurosynth nach Ähnlichkeit gruppieren

Wir haben gesagt, dass die 602 Karten in Cluster eingeteilt sind. Können wir das irgendwie darstellen? Ja, indem wir die 18744 Dimensionen (jeder Voxel ist eine Dimension) auf 2 Dimensionen projizieren. Dazu verwenden wir Multidimensionale Skalierung.

In [25]:
# hier verwenden wir Daten die ich vorbereitet habe
dissDf = pd.read_csv('../arrays/dissDf.csv',index_col=[0])
mdsPositions = np.array(pd.read_csv('../arrays/mdsDf.csv',index_col=[0]))
mdsDf = pd.DataFrame(mdsPositions,index=dissDf.index)
In [26]:
# plotting
import matplotlib.pyplot as plt
from matplotlib import gridspec
import seaborn as sns
%matplotlib inline

Acht Fraben für die acht Cluster:

In [27]:
myPalette = sns.color_palette('Set1',n_colors=8)
sns.palplot(myPalette)

Brain Space

In [28]:
# laden von vorbereiteten Sachen
mdsDf = pd.read_csv('../arrays/mdsDf.csv',index_col=[0])
kDf = pd.read_csv('../arrays/kDf.csv',index_col=[0])

Abbildung erstellen

In [29]:
def findNeighbors(mdsDf,p,added,notCloserThan=50):
    
    # coordinates of this keyword
    thisDf = mdsDf.loc[p]
    
    # coordinates of all other keywords
    otherDf = mdsDf.drop(p)
    
    # lenghts of adjacent and opposite
    diffDf = abs(thisDf-otherDf)
    
    # lengths of hypoteneuse
    distanceDf = np.sqrt(diffDf**2).sum(axis=1)
    
    # check if there are close distances
    closeEncounters = distanceDf[distanceDf<notCloserThan].index
    
    # check if the close ones have already been labelled
    for entry in closeEncounters:
        if entry in added:
            return True
    
    return False
In [30]:
def plotSpace(mdsDf,kDf,clusterNames,myPalette,closest,ax):

    kPredictions = list(kDf['n'])
    # loop both trough the positions and the predictions
    for p,l in zip(mdsDf.index,kPredictions):
        # show predictions from raw data on mds scaled data, the predictions are indicated by the color
        ax.plot( mdsDf.ix[p]['0'],
                     mdsDf.ix[p]['1'],
                     'o',color=myPalette[l],
                      markersize=12,alpha=0.8
               )

    added = []
    mdsDf = mdsDf.sort_values(by='1')
    # sorting by the x-dimension will fill the labels from right to left side
    mdsDf = mdsDf.sort_values(by='0',ascending=False)
    for p,x,y in zip(mdsDf.index,mdsDf['0'], mdsDf['1']):
        l = kDf.loc[p]
        if not findNeighbors(mdsDf,p,added,notCloserThan=closest):
            ax.annotate(p, xy = (x, y),fontsize=16,alpha=0.8)
            added.append(p)
            
    # dummy plot for labelling
    for l in np.unique(kDf['n']):
        ax.plot([],'o',color=myPalette[l],label=clusterNames[str(l)])
    
    # show the plot
    sns.despine(left=True,bottom=True)
    ax.set_xticks([]);ax.set_yticks([])
    ax.legend(loc='lower left',bbox_to_anchor=(0.,0))
    return ax

Einstellungen für Abbildung

In [31]:
sns.set_style('white')
sns.set_context('poster')

der große Ball

In [32]:
fig,ax = plt.subplots(1,1,figsize=(16,16))
ax = plotSpace(mdsDf,kDf,clusterNames,myPalette,50,ax)
plt.show()

Was ist das? Jede der 602 Karten in Neurosynth wurde mit jeder anderen korreliert. Das gibt 602x602=362404 Korrelationen.
Wir machen aus den Korrelationen Distanzen, indem wir 1-Korrelation rechnen. Perfekte Korrelationen von 1 haben eine Distanz von 0 und negative Korrelationen von -1 haben eine Distanz von 2. Alle anderen liegen dazwischen. Dann nehmen wir diese Distanzen im 18744-Dimensionalen Raum (jeder Voxel ist eine Dimension) und projizieren sie auf 2. Dabei geht zwar viel Information verloren, aber weniger als man denken würde. Da wir außerdem eine Clusteranalyse im 18744-Dimnesionalen Raum gerechnet haben, können wir jedem Punkt auf der Karte eine Farbe geben, die anzeigt, zu welchem Cluster der Punkt gehört. Dabei sehen wir, dass die Cluster ganz gut in 2D dargestellt werden können.

Was sagt uns das? Je näher sich zwei Punkte sind, desto ähnlicher sind sich die Aktivierungsmuster für das jeweilige Stichwort in Neurosynth. Für sich genommen ist schon interessant, wie gut inhaltlich/psychologisch interpretierbar diese Ähnlichkeiten sind.

der Ball - Teil 2

Jetzt haben wir zwar alle Karten in Neurosynth miteinander korreliert, aber unsere eigenen Daten aber gar nicht verwendet um den Ball zu erstellen. Dabei hatten wir doch oben eine Tabelle mit Korrelationen. Um diese jetzt auf dem Ball darzustellen, variieren wir die Größe der Punkte. Je höher die Korrelation unserer Karte mit einem Punkt (z.B. "face", "lexical" etc.), desto größer wird der Punkt.

Dabei schummeln wir, indem wir die Größe exponentiell variieren. D.h. die Unterschiede in unserem Ball sehen viel viel größer aus als sie tatsächlich sind. Das ist aber der einzige Weg, dass das resultierende Bild dann noch halbwegs übersichtlich und lesbar ist. Außerdem simuliert das auch in gewisser Weise einen "winner take all" Algorithmus.

In [33]:
# Skalierung der Korrelationen von 0 bis 1
def makeMinMax(corrDf):
    minMaxDf = pd.DataFrame( preprocessing.minmax_scale(corrDf,axis=1),
                            index=corrDf.index,
                            columns=corrDf.columns )
    return minMaxDf.T
In [34]:
minMaxDf = makeMinMax(thisCorrDf)

Abbildung machen

In [35]:
def plotCorr(mdsDf,kDf,minMaxDf,myPalette,clusterNames,closest,ax):

    # loop both trough the positions and the predictions
    for p in mdsDf.index:
        l = kDf['n'].loc[p]
        # show predictions from raw data on mds scaled data, the predictions are indicated by the color
        ax.plot( mdsDf.ix[p]['0'],
                     mdsDf.ix[p]['1'],
                     'o',color=myPalette[l],
                      markersize=minMaxDf.ix[l].ix[p]**3*50,
                      alpha=0.7
               )

    # to not omit the most important keywords, we move through the list by the order in minMaxDf
    sortedIndex = minMaxDf.sort_values('corr',ascending=False).index.labels[1]
    sortedNames = [minMaxDf.index.levels[1][x] for x in sortedIndex ]
    #print sortedNames[:10]
    added = []
    for p in sortedNames:
        l = kDf['n'].loc[p]
        x = mdsDf['0'].loc[p]
        y = mdsDf['1'].loc[p]

        if not findNeighbors(mdsDf,p,added,notCloserThan=closest):

            thisVal = minMaxDf.ix[l].ix[p].values[-1]
            
            ax.annotate(p, xy = (x, y),
                    fontsize=thisVal**3*50,
                    alpha=thisVal**5)
            added.append(p)

    # dummy plot for labelling
    for l in np.unique(kDf['n']):
        ax.plot([],'o',color=myPalette[l],label=clusterNames[str(l)])
    
    # show the plot
    sns.despine(left=True,bottom=True)
    ax.set_xticks([]);ax.set_yticks([])
    #ax.legend(loc='lower left',bbox_to_anchor=(1.5,0))
    return ax
In [36]:
fig,ax = plt.subplots(1,1,figsize=(8,8))
plotCorr(mdsDf,kDf,minMaxDf,myPalette,clusterNames,100,ax)
plt.show()

Sanity Checks

In [37]:
def makeMindSpace(thisMap,
                  my_masker=my_masker,nsData=nsData,mdsDf=mdsDf,kDf=kDf,
                  myPalette=myPalette,clusterNames=clusterNames):

    scaleMap = extractMaps(thisMap,my_masker)

    thisCorr = np.corrcoef(scaleMap,nsData)[0,:][1:]
    
    thisCorrDf = pd.DataFrame(thisCorr,index=nsData.index,columns=['corr']).T
    
    minMaxDf = makeMinMax(thisCorrDf)

    fig,ax = plt.subplots(1,1,figsize=(8,8))
    
    plotCorr(mdsDf,kDf,minMaxDf,myPalette,clusterNames,50,ax)
    
    imgName = thisMap.split('/')[-1].split('.')[0]
    cond,num,content = imgName.split('_')
    plt.title('%s %s %s' % (cond,num,content))
    
    plt.show()
In [38]:
makeMindSpace('../ns/autobiographical memory_pFgA_pF=0.50_FDR_0.01.nii.gz')
In [39]:
makeMindSpace('../ns/language comprehension_pFgA_pF=0.50_FDR_0.01.nii.gz')
In [40]:
makeMindSpace('../ns/emotionally_pFgA_pF=0.50_FDR_0.01.nii.gz')

Das machen wir jetzt für alle 40 unserer Trainingsblöcke

In [41]:
def sortBlocks(blocks):
    d = {}
    for i in blocks:
        num = i.split('/')[-1].split('.')[0].split('_')[1]
        d[int(num)] = i
    sortRunDf = pd.DataFrame(d,index=['filename']).T
    sortRunDf.sort_index(inplace=True)
    return sortRunDf
In [42]:
sortRunDf = sortBlocks(imgList)
In [43]:
sortRunDf
Out[43]:
filename
1 ../training/s00SPRACHE_001_Sprechen-Tiere.nii.gz
2 ../training/s00MOTORIK_002_Haende-Jonglieren.n...
3 ../training/s00GESICHTER_003_Bekannt-Freunde.n...
4 ../training/s00EMOTION_004_Negativ-Sturm.nii.gz
5 ../training/s00RUHE_005_Ruhe.nii.gz
6 ../training/s00MOTORIK_006_Fuesse-Balltreten.n...
7 ../training/s00EMOTION_007_Positiv-Wald.nii.gz
8 ../training/s00GESICHTER_008_Beruehmt-Filmscha...
9 ../training/s00SPRACHE_009_Schreiben-Lebensmit...
10 ../training/s00RUHE_010_Ruhe.nii.gz
11 ../training/s00GESICHTER_011_Bekannt-Familie.n...
12 ../training/s00MOTORIK_012_Haende-Kanu.nii.gz
13 ../training/s00EMOTION_013_Negativ-Klippe.nii.gz
14 ../training/s00SPRACHE_014_Sprechen-Staedte.ni...
15 ../training/s00RUHE_015_Ruhe.nii.gz
16 ../training/s00EMOTION_016_Positiv-Strand.nii.gz
17 ../training/s00GESICHTER_017_Beruehmt-Musiker....
18 ../training/s00MOTORIK_018_Fuesse-Fahrrad.nii.gz
19 ../training/s00SPRACHE_019_Schreiben-Vornamen....
20 ../training/s00RUHE_020_Ruhe.nii.gz
21 ../training/s00MOTORIK_021_Haende-Boxen.nii.gz
22 ../training/s00GESICHTER_022_Bekannt-Kommilito...
23 ../training/s00SPRACHE_023_Sprechen-Lebensmitt...
24 ../training/s00EMOTION_024_Negativ-Waldbrand.n...
25 ../training/s00RUHE_025_Ruhe.nii.gz
26 ../training/s00GESICHTER_026_Beruehmt-Seriensc...
27 ../training/s00SPRACHE_027_Schreiben-Tiere.nii.gz
28 ../training/s00MOTORIK_028_Fuesse-Hochseil.nii.gz
29 ../training/s00EMOTION_029_Positiv-See.nii.gz
30 ../training/s00RUHE_030_Ruhe.nii.gz
31 ../training/s00SPRACHE_031_Sprechen-Vornamen.n...
32 ../training/s00GESICHTER_032_Bekannt-Schulfreu...
33 ../training/s00EMOTION_033_Negativ-Strand.nii.gz
34 ../training/s00MOTORIK_034_Haende-Ballwerfen.n...
35 ../training/s00RUHE_035_Ruhe.nii.gz
36 ../training/s00EMOTION_036_Positiv-Berg.nii.gz
37 ../training/s00SPRACHE_037_Schreiben-Staedte.n...
38 ../training/s00GESICHTER_038_Beruehmt-Sportler...
39 ../training/s00MOTORIK_039_Fuesse-Trampolin.ni...
40 ../training/s00RUHE_040_Ruhe.nii.gz
In [44]:
for i in sortRunDf.index:
    thisBlock = sortRunDf.ix[i]['filename']
    ax = makeMindSpace(thisBlock)
In [ ]: